#include <iostream>
#include <thread>
#include <chrono>
#include <atomic>
#include <iomanip>
#include <sched.h>
#include <fstream>
#include <sstream>
#include <vector>

// 获取CPU核心数
unsigned int get_cpu_cores() {
    return std::thread::hardware_concurrency();
}

// 绑定线程到指定核心
void set_thread_affinity(int core_id) {
    cpu_set_t cpuset;
    CPU_ZERO(&cpuset);
    CPU_SET(core_id, &cpuset); // 绑定到core_id指定的核心
    if (pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset) != 0) {
        std::cerr << "Failed to set thread affinity to core " << core_id << std::endl;
    }
}

// 读取/proc/stat文件，获取指定核心的CPU时间
std::vector<unsigned long long> read_core_times(int core_id) {
    std::ifstream proc_stat("/proc/stat");
    std::string line;
    std::vector<unsigned long long> core_times;

    // 查找指定核心的行
    for (int i = 0; i <= core_id + 1; ++i) {
        if (!std::getline(proc_stat, line)) {
            return core_times;
        }
    }

    std::istringstream iss(line);
    std::string cpu_label;
    iss >> cpu_label; // 跳过"cpuX"标签
    unsigned long long time;
    while (iss >> time) {
        core_times.push_back(time);
    }

    return core_times;
}

// 计算指定核心的CPU占用率
double calculate_core_usage(const std::vector<unsigned long long>& prev_times,
                            const std::vector<unsigned long long>& curr_times) {
    unsigned long long prev_idle = prev_times[3]; // idle时间
    unsigned long long curr_idle = curr_times[3];

    unsigned long long prev_total = 0;
    unsigned long long curr_total = 0;

    for (size_t i = 0; i < prev_times.size(); ++i) {
        prev_total += prev_times[i];
        curr_total += curr_times[i];
    }

    unsigned long long total_diff = curr_total - prev_total;
    unsigned long long idle_diff = curr_idle - prev_idle;

    if (total_diff == 0) {
        return 0.0;
    }

    return 100.0 * (1.0 - static_cast<double>(idle_diff) / total_diff);
}

// 线程函数，模拟固定核心的CPU占用率
void worker(int core_id, std::atomic<bool>& running, double target_usage) {
    set_thread_affinity(core_id); // 绑定线程到指定核心

    // 将百分比转换为小数
    double usage_ratio = target_usage / 100.0;

    while (running) {
        // 计算占用CPU的时间（单位：毫秒）
        auto busy_time = std::chrono::milliseconds(static_cast<int>(1000 * usage_ratio));
        // 计算空闲时间（单位：毫秒）
        auto idle_time = std::chrono::milliseconds(1000 - static_cast<int>(1000 * usage_ratio));

        // 占用CPU
        auto start = std::chrono::steady_clock::now();
        while (std::chrono::steady_clock::now() - start < busy_time) {
            // 空循环，占用CPU
        }

        // 释放CPU
        std::this_thread::sleep_for(idle_time);
    }
}

// 打印指定核心的CPU占用率
void monitor_core_usage(int core_id, std::atomic<bool>& running) {
    std::vector<unsigned long long> prev_times = read_core_times(core_id);

    while (running) {
        std::this_thread::sleep_for(std::chrono::seconds(1)); // 每秒打印一次

        std::vector<unsigned long long> curr_times = read_core_times(core_id);
        double core_usage = calculate_core_usage(prev_times, curr_times);

        std::cout << "Core " << core_id << " Usage: " << std::fixed << std::setprecision(2) << core_usage << "%" << std::endl;

        prev_times = curr_times;
    }
}

int main() {
    unsigned int num_cores = get_cpu_cores();
    std::cout << "Number of CPU cores: " << num_cores << std::endl;

    int core_id;
    double target_usage;

    // 输入校验
    do {
        std::cout << "请输入核心编号（0 ~ " << num_cores - 1 << "）和目标CPU占用率（%）：";
        std::cin >> core_id >> target_usage;
        std::cin.get();
    } while (core_id < 0 || core_id >= num_cores || target_usage < 0 || target_usage > 100);

    std::atomic<bool> running(true);

    // 启动工作线程，绑定到指定核心
    std::thread worker_thread(worker, core_id, std::ref(running), target_usage);

    // 启动监控线程，监控指定核心的CPU占用率
    std::thread monitor_thread(monitor_core_usage, core_id, std::ref(running));

    // 主线程等待用户输入回车键以停止程序
    std::cout << "Press Enter to stop..." << std::endl;
    std::cin.get();

    // 停止所有线程
    running = false;

    // 等待线程完成
    worker_thread.join();
    monitor_thread.join();

    std::cout << "Program stopped." << std::endl;
    return 0;
}